//
//  drawingCanvas.m
//  RapidMo
//
//  Created by Michael on 10.09.09.
//  Copyright 2009 Artgruppe inc. All rights reserved.

#import "drawingCanvas.h"
#include "Constants.h"
#include "MyMath.h"

#define pi 3.1415
#define kOffsetArcX 	-7
#define kOffsetArcY 	-7
// I cannot calculate arc here normally,
// so I have to make this cheat scheme:
#define kArc1Ang1 	2.377681
#define kArc1Ang2 	1.86

#define kArc2Ang1 	1.846235
#define kArc2Ang2 	1.406463

#define kArc3Ang1 	1.410566
#define kArc3Ang2 	1.217310

#define kArc4Ang1 	1.214359
#define kArc4Ang2 	0.607100

#define kArc5Ang1 	0.605858
#define kArc5Ang2 	0.139786

#define kArc6Ang1 	5.490510
#define kArc6Ang2 	0.139786

#define kArc7Ang1 	5.490510
#define kArc7Ang2 	5.209546

#define kArc8Ang1 	5.189243
#define kArc8Ang2 	4.451694

#define kArc9Ang1 	4.455226
#define kArc9Ang2 	3.958916

#define kArc10Ang1 	3.958916
#define kArc10Ang2 	3.379188

#define kArc11Ang1 	3.379188
#define kArc11Ang2 	2.71

#define kArc12Ang1 	2.71
#define kArc12Ang2 	2.377681	
// end of cheating

@implementation drawingCanvas
@synthesize backgroundColor;
@synthesize scroll;
@synthesize _viewLines, _viewCircles;

-(void)initization
{
    _bFirstPointOfLineWasDrawn=false;
    _nCurMaxSize=kMaxItems;
    _objectsToDraw=(DrawItem**)malloc(sizeof(DrawItem)*_nCurMaxSize);

    _nCount=0;
    _fLineWidth=5.0;

    _drawingRect=CGRectMake(0, 0, 0, 0);
    self.backgroundColor = [UIColor whiteColor];
    self._viewCircles=nil;
    self._viewLines=nil;
}

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {						
		[self initization];
	}
    return self;
}

-(void) setLineWidth:(float)width
{
    _fLineWidth=width;
}

-(void) createBitmapLines
{
    // create the size of our bitmap:
    CGSize size=CGSizeMake(_drawingRect.size.width, 
	    _drawingRect.size.height);

    UIGraphicsBeginImageContext(size);

    // then get the context:
    CGContextRef context = UIGraphicsGetCurrentContext();
    // we draw all the elements twice:
    // first cap lines or/and lines
    // then the lines themselves;
    for(int capOrNot=0; capOrNot<2; capOrNot++){
	// draw our lines:
	[self drawLines: context withCap: capOrNot];
	// now try to draw our arcs:
	[self drawArcs: context withCap:capOrNot];
    }
    // get the image with our lines from the context:
    UIImage* imgLines = UIGraphicsGetImageFromCurrentImageContext(); 
    //[_imgLines retain];
    // we've drawn the image to the bitmap, do not do it anymore:
    _bDrawToBitmapLines=false;
    UIGraphicsEndImageContext();

    UIImageView* viewLines=[[UIImageView alloc] initWithImage: imgLines];

    viewLines.center=CGPointMake(_drawingRect.origin.x+imgLines.size.width/2,
	    _drawingRect.origin.y+imgLines.size.height/2);
    self._viewLines=viewLines;
    [viewLines release];
    [scroll addSubview: self._viewLines];
}

-(void) drawArcs: (CGContextRef) context withCap:(int)capOrNot
{
    int nLastArcNum=-1;
    for(int i=0; i<_nCount; i++)
    {
	DrawItem* item=_objectsToDraw[i];
	if(capOrNot==kNotCapType){
	    CGContextSetStrokeColorWithColor(context, item.color.CGColor);
	    CGContextSetFillColorWithColor(context, item.color.CGColor);
	}
	else
	{
	    CGContextSetStrokeColorWithColor(context, backgroundColor.CGColor);
	    CGContextSetFillColorWithColor(context, backgroundColor.CGColor);
	}

	CGContextSetLineCap(context, kCGLineCapRound);
	CGContextSetLineJoin(context, kCGLineJoinRound);

	if(item.type==TYPE_ARC){
	    if(capOrNot==kNotCapType)
		CGContextSetLineWidth(context, _fLineWidth);
	    else
		CGContextSetLineWidth(context, _fLineWidth+kBorder);

	    if(nLastArcNum==-1)
	    {
		nLastArcNum=item.nodeNum;
	    }
	    else{
		double angle1;
		double angle2;
		bool ccw;

		int nMaxArcNum=maxA(item.nodeNum, nLastArcNum);
		int nArcIndex=nMaxArcNum-68;	

		if((nLastArcNum==79 && item.nodeNum==68) ||
			(nLastArcNum==68 && item.nodeNum==79))
		    nArcIndex=12;	

		ccw=true;

		switch(nArcIndex)
		{
		    case 1:
			angle1=kArc1Ang1;
			angle2=kArc1Ang2;
			break;
		    case 2:
			angle1=kArc2Ang1;
			angle2=kArc2Ang2;
			break;
		    case 3:
			angle1=kArc3Ang1;
			angle2=kArc3Ang2;
			break;
		    case 4:
			angle1=kArc4Ang1;
			angle2=kArc4Ang2;

			break;
		    case 5:
			angle1=kArc5Ang1;
			angle2=kArc5Ang2;

			break;
		    case 6:
			angle1=kArc6Ang1;
			angle2=kArc6Ang2;
			ccw=false;
			//ccw=!ccw;

			break;
		    case 7:
			angle1=kArc7Ang1;
			angle2=kArc7Ang2;

			break;
		    case 8:
			angle1=kArc8Ang1;
			angle2=kArc8Ang2;

			break;
		    case 9:
			angle1=kArc9Ang1;
			angle2=kArc9Ang2;

			break;
		    case 10:				
			angle1=kArc10Ang1;
			angle2=kArc10Ang2;

			break;
		    case 11:
			angle1=kArc11Ang1;
			angle2=kArc11Ang2;	

			break;
		    case 12:
			angle1=kArc12Ang1;
			angle2=kArc12Ang2;
			break;
		}		


		CGContextAddArc(context, kCenterRadialX-_drawingRect.origin.x, 
			kCenterRadialY-_drawingRect.origin.y,
			200, 
			angle1, angle2, ccw);
		// arc must be separate!
		CGContextStrokePath(context);			
		nLastArcNum=item.nodeNum;	
	    }
	}
    }
}

-(void) drawLines: (CGContextRef) context withCap:(int)capOrNot
{
    _bFirstPointOfLineWasDrawn=false;
    _ptArcLast= CGPointMake(0,0);
    CGPoint ptSecondLastArc = CGPointMake(0,0);
    bool bLineWasAdded=false;    
    //printf("Cycle!\n");
    for(int i=0; i<_nCount; i++)
    {		
	DrawItem* item=_objectsToDraw[i];
	if(capOrNot==kNotCapType){
	    CGContextSetStrokeColorWithColor(context, item.color.CGColor);
	    CGContextSetFillColorWithColor(context, item.color.CGColor);
	}
	else
	{
	    CGContextSetStrokeColorWithColor(context, backgroundColor.CGColor);
	    CGContextSetFillColorWithColor(context, backgroundColor.CGColor);
	}

	CGContextSetLineCap(context, kCGLineCapRound);
	CGContextSetLineJoin(context, kCGLineJoinRound);

	if(item.type==TYPE_LINE){
	    //printf("Drawing Line: %.0f, %.0f\n", item.center.x, item.center.y);
	    if(capOrNot==kNotCapType)
		CGContextSetLineWidth(context, _fLineWidth);
	    else
		CGContextSetLineWidth(context, _fLineWidth+kBorder);

	    if(!_bFirstPointOfLineWasDrawn){
		_bFirstPointOfLineWasDrawn=true;
		CGContextMoveToPoint(context, item.center.x-_drawingRect.origin.x, 
			item.center.y-_drawingRect.origin.y);
	    }
	    else{
		
		CGContextAddLineToPoint(context, item.center.x-_drawingRect.origin.x,
			item.center.y-_drawingRect.origin.y);
	    }
	    bLineWasAdded=true;
	    /*
	    //if(bArcWasAdded)
	    //   CGContextStrokePath(context);
	    bArcWasAdded=false;
	    */
	}
	else if(item.type==TYPE_ARC){
	    if(bLineWasAdded){
		CGContextAddLineToPoint(context, item.center.x-_drawingRect.origin.x,
			item.center.y-_drawingRect.origin.y);
		bLineWasAdded=false;
	    }
	    if(i+1<_nCount){
	    DrawItem* itemNext=_objectsToDraw[i+1];
	    if(itemNext.type==TYPE_LINE)
		CGContextMoveToPoint(context, item.center.x-_drawingRect.origin.x,
			item.center.y-_drawingRect.origin.y);
	    }
	    //printf("Arc nums; Last: %d, Next: %d\n", nLastArcNum, item.nodeNum);
	    //nLastArcNum=item.nodeNum;
	}
	else if(item.type== TYPE_IMAGE){	    
		CGPoint drawPoint = CGPointMake(item.center.x-_drawingRect.origin.x
		    -item.image.size.width/2,
		    item.center.y-_drawingRect.origin.y
		    -item.image.size.height/2);
	    CGRect rectImage;
	    rectImage.origin=drawPoint;
	    rectImage.size=item.image.size;		
		 /*
		[item.image drawInRect:rectImage blendMode: kCGBlendModeNormal
					 alpha: 0.3f];
		 */
	    [item.image drawInRect:rectImage];
	}			
	else if(item.type== TYPE_FOG){	
		[self removeFog];
			
		fogView=[[UIImageView alloc] initWithImage: item.image];
		fogView.center = item.center;
		fogView.alpha=0.3f;			
		
		[scroll addSubview: fogView];
	}		
    }
    if(_bFirstPointOfLineWasDrawn)			
	CGContextStrokePath(context);



}

-(void) removeFog
{
	if(fogView!=nil){
		[fogView removeFromSuperview];
		[fogView release];
		fogView=nil;
	}	
}

-(void) createBitmapCircles
{
    // create the size of our bitmap:
    CGSize size=CGSizeMake(_drawingRect.size.width, 
	    _drawingRect.size.height);

    UIGraphicsBeginImageContext(size);

    // then get the context:
    CGContextRef context = UIGraphicsGetCurrentContext();
    // then draw our ellipses:
    for(int i=0; i<_nCount; i++)
    {		    
	DrawItem* item=_objectsToDraw[i];

	CGContextSetStrokeColorWithColor(context, item.color.CGColor);
	CGContextSetFillColorWithColor(context, item.color.CGColor);					

	switch(item.type){				
	    case TYPE_CIRCLE:
		CGRect rectC=CGRectMake(item.center.x-item.rad-_drawingRect.origin.x,
			item.center.y-item.rad-_drawingRect.origin.y,
			2*item.rad,2*item.rad);
		CGContextSetLineWidth(context, 2.0);
		CGContextAddEllipseInRect(context, rectC);
		CGContextDrawPath(context, kCGPathFillStroke);
		break;	
	}	
    }		
    // get the image with our circles from the context:
    UIImage* imgCircles = UIGraphicsGetImageFromCurrentImageContext(); 

    // we've draw the image to the bitmap, do not do it anymore:
    _bDrawToBitmapCircles=false;
    UIGraphicsEndImageContext(); 

    // add that stuff the scroll bar:
    UIImageView* viewCircles=[[UIImageView alloc] initWithImage: imgCircles];
    viewCircles.center=CGPointMake(_drawingRect.origin.x+imgCircles.size.width/2, 
	    _drawingRect.origin.y+imgCircles.size.height/2);
    //NSArray* array=[NSArray arrayWithObjects: imgCircles, imgCircles2, nil];
    /*
    viewCircles.animationImages=item.animPictures;
    viewCircles.animationDuration = item.animationDuration; 
    */
    self._viewCircles=viewCircles;
    [viewCircles release];
    [scroll addSubview: self._viewCircles];
	//[imgCircles release];
    //[self._viewCircles startAnimating];
}

-(void) createAnimationViews
{
    int nOldCount=_nAnimationsCount;
    // go through the objects and find out, if we've got animation there:
    _nAnimationsCount=0;
    for(int i=0; i<_nCount; i++)
	if(_objectsToDraw[i].type==TYPE_ANIMATION)
	    _nAnimationsCount++;
    // delete old memory and alloc new one: 
    if(_aViewAnimations!=nil)
    {
	//printf("Recreating animation views, count: %d!\n", nOldCount);
	for(int i=0; i<nOldCount; i++)
	    [_aViewAnimations[i] removeFromSuperview];
	free(_aViewAnimations);


	_aViewAnimations=(UIImageView**)malloc(sizeof(UIImageView)*_nAnimationsCount);
    }
    else //(_aViewAnimations==nil)
	_aViewAnimations=(UIImageView**)malloc(sizeof(UIImageView)*_nAnimationsCount);

    // now create all that views:
    int nCur=0;
    for(int i=0; i<_nCount; i++)
    {
	if(_objectsToDraw[i].type==TYPE_ANIMATION)
	    [self createAnimationView: i withIndexInAnimations: nCur++];
    }
}

-(void) createAnimationView:(int)indexInDB withIndexInAnimations:(int)indexAnim
{
    //printf("Creating view %d\n", indexAnim);
    DrawItem* item=_objectsToDraw[indexInDB];
    UIImage* image=((UIImage*)[item.animPictures objectAtIndex:0]);
    CGSize size=CGSizeMake(image.size.width,
	    image.size.height);

    UIGraphicsBeginImageContext(size);

    // then get the context:
    //CGContextRef context = UIGraphicsGetCurrentContext();
    // then draw our ellipses:

    //item.image=image;
    /*
    CGPoint drawPoint = CGPointMake(0,0);
    CGRect rectImage;
    rectImage.origin=drawPoint;
    rectImage.size=image.size;
    */

    //[image drawInRect:rectImage];

    // get the image with our circles from the context:
    UIImage* imgCircles = UIGraphicsGetImageFromCurrentImageContext(); 

    //UIGraphicsEndImageContext(); 

    // add that stuff the scroll bar:
    UIImageView* viewCircles=[[UIImageView alloc] initWithImage: imgCircles];
    viewCircles.center=  CGPointMake(item.center.x,
	    item.center.y);
  //NSArray* array=[NSArray arrayWithObjects: imgCircles, imgCircles2, nil];
    viewCircles.alpha=0.8f;
    viewCircles.animationImages=item.animPictures;
    viewCircles.animationDuration = item.animationDuration; 

    _aViewAnimations[indexAnim]=viewCircles;
    //[viewCircles retain];
    [scroll addSubview: _aViewAnimations[indexAnim]];
    [_aViewAnimations[indexAnim] startAnimating];
}

- (void)drawRect:(CGRect)rect {

}

-(void) DrawThemAll
{
    if(_bDrawToBitmapCircles)
	[self createBitmapCircles];
    if(_bDrawToBitmapLines)
	[self createBitmapLines];
    [self createAnimationViews];
    // do not use uneeded elements:
    [self freeElements];
}

-(void) utilization
{
    if(self._viewCircles!=nil)
    {
	[self._viewCircles removeFromSuperview];
	//[self._viewCircles release];
	self._viewCircles=nil;
    }

    if(self._viewLines!=nil)
    {
	[self._viewLines removeFromSuperview];
	//[self._viewLines release];
	self._viewLines=nil;
    }
	
    [self removeFog];
    _nCount=0;    
    free(_objectsToDraw);
    _objectsToDraw=nil;
}

-(void) freeElements
{
    for(int i=0; i<_nCount; i++){
		/*
		switch (_objectsToDraw[i].type) {
			case TYPE_LINE:
				[_objectsToDraw[i].color release];
				break;
			case TYPE_ARC:
				[_objectsToDraw[i].color release];
				break;				
			case TYPE_IMAGE:
				[_objectsToDraw[i].image release];
				break;	
			case TYPE_ANIMATION:
				[_objectsToDraw[i].animPictures release];
				break;	
			default:
				break;
		}
		 */
		_objectsToDraw[i].color=nil;
		_objectsToDraw[i].image=nil;
		_objectsToDraw[i].animPictures=nil;
		[_objectsToDraw[i] release];
	}
    _nCount=0;
}

-(void)addObjectToDraw:(DrawItem*)object
{	
    // update area to draw:
    CGRect rectWithoutShifting;
    if(object.type==TYPE_CIRCLE || object.type==TYPE_ANIMATION){
	rectWithoutShifting=CGRectMake(
		object.center.x-object.rad-kShiftCanvasX, 
		object.center.y-object.rad-kShiftCanvasY, 
		2*object.rad+kShiftCanvasX*2,
		2*object.rad+kShiftCanvasY*2);

	_bDrawToBitmapCircles=true;
    }
    else if(object.type==TYPE_LINE || object.type==TYPE_ARC){
	if(_ptLastLine.x!=0 && _ptLastLine.y!=0)
	    rectWithoutShifting=CGRectMake(
		    fmin(object.center.x, _ptLastLine.x), 
		    fmin(object.center.y, _ptLastLine.y), 
		    fabs(object.center.x-_ptLastLine.x),
		    fabs(object.center.y-_ptLastLine.y));

	_ptLastLine=object.center;
	_bDrawToBitmapLines=true;
    }

    if(_drawingRect.origin.x==0.0f && 
	    _drawingRect.origin.y==0.0f && 
	    _drawingRect.size.width==0.0f && 
	    _drawingRect.size.height==0.0f)
	_drawingRect=rectWithoutShifting;
    else
	_drawingRect=CGRectUnion(_drawingRect, rectWithoutShifting);

    if(object.type==TYPE_LINE)
	_drawingRect=CGRectMake(_drawingRect.origin.x-kShiftCanvasX, 
		_drawingRect.origin.y-kShiftCanvasY, 
		_drawingRect.size.width+kShiftCanvasX*10, 
		_drawingRect.size.height+kShiftCanvasY*10);	

    if(_nCount<_nCurMaxSize){	
	_objectsToDraw[_nCount++]=object;
    }
    else{
	// reform the array:
	DrawItem** oldArray=_objectsToDraw;
	_objectsToDraw=(DrawItem**)malloc(sizeof(DrawItem)*(_nCurMaxSize+_nCurMaxSize/2));
	for(int i=0; i<_nCurMaxSize; i++)		
	    _objectsToDraw[i]=oldArray[i];			
	free(oldArray);
	_nCurMaxSize=_nCurMaxSize+_nCurMaxSize/2;
	[self addObjectToDraw:object];
    }
}

-(void) addObjecsToDraw:(DrawItem**)objects withCount:(int)count
{
    // that method was never used in my program!
    if(_objectsToDraw!=nil)
	free(_objectsToDraw);
    _objectsToDraw=objects;	
    _nCount=count;
    //_bHaveToReadraw=true;
    _drawingRect=CGRectMake(0, 0, 0, 0);	
}

-(void) haveToDestroyBuffer
{
    //printf("Objects were removed!\n");
    if(self._viewCircles!=nil)
    {
	[self._viewCircles removeFromSuperview];
	//[self._viewCircles release];
	self._viewCircles=nil;
    }

    if(self._viewLines!=nil)
    {
	[self._viewLines removeFromSuperview];
	//[self._viewLines release];
	self._viewLines=nil;
    }

    /*
    for(int i=0; i<_nCount; i++)	
	[_objectsToDraw[i] release];
    _nCount=0;
    */

    _drawingRect=CGRectMake(0, 0, 0, 0);
    _ptLastLine=CGPointMake(0, 0);
    _bFirstPointOfLineWasDrawn=false;
    _bDrawToBitmapLines=true;
    _bDrawToBitmapCircles=true;	
}

-(void) supplyShifting:(CGPoint)pt
{
}

- (void)dealloc {
    [super dealloc];	
}
@end
